package core.agent;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.tilab.mmp.provisioner.Provisioner;

import core.api.DFservice;
import core.datamodel.Constants;
import core.datamodel.Event;
import core.datamodel.Resource;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.WakerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import jade.util.Logger;
/**
 * Questo agente ha il compito di eseguire determinate azioni su richiesta
 * Il messaggio che viene inviato ha un parametro TYPE che definisce il tipo di contenuto
 * @author 00917720
 *
 */
public class AgentExecutor extends Agent {

	private Logger log = Logger.getJADELogger(this.getClass().getName());
	private DFservice DFsrv = new DFservice();

	protected void setup() {

		DFsrv.registerAgent("executor", this);

		// Add the behaviour serving queries from controller agent
		addBehaviour(new RequestExecutionServer());

	}

	// Put agent clean-up operations here
	protected void takeDown() {
		// Deregister from the yellow pages
		try {
			DFService.deregister(this);
		}
		catch (FIPAException fe) {
			fe.printStackTrace();
		}

	}
	private class RequestExecutionServer extends CyclicBehaviour {
		private Event event;

		@Override
		public void action() {

			MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
			ACLMessage msg = myAgent.receive(mt);

			if (msg != null && "EVENT".equals(msg.getUserDefinedParameter("TYPE"))) {

				// Recupero i dati delle richiesta
				try {
					event = (Event) msg.getContentObject();
				} catch (UnreadableException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

				// dato l'evento provvedo ad eseguire le azioni previste
				// azioni da eseguire se ho una nuova vm ...
				// ad esempio atttivare alcune azioni.

				log.info( "Ricevuto un azione di tipo "+ event.getAction() );

				if (event.getAction().equals(Constants.EVENT_ACTION_NEW) | 
						event.getAction().equals(Constants.EVENT_ACTION_DELETE)	){

					log.info("Eseguo Azioni di aggiornamento  verso Mconsole ");
					// normalizzazioni a supporto script di pino

					Resource  rsc = event.getEventResource();
					rsc.setCustomer("Cliente_Tilab");
					event.setEventResource(rsc);		

					// inserisco un wait di n-sec. nel solo caso di aggiornamento VM
					if ( Constants.RESOURCE_TYPE_VIRTUAL_MACHINE.equals(rsc.getResourceType())) {
						addBehaviour(new WakerBehaviour(myAgent, 10000) {
							public void onWake() {
								eventToMconsole(event);
							}
						});
					} else {
						eventToMconsole(event);
					}

				}




				// TEST
				/**
				 * 

			try {

				    // Execute a command without arguments

				    String command = "cmd /c dir"; // eseguo di da dos
				    log.info("Eseguo comando: "+ command);
				    Process child = Runtime.getRuntime().exec(command);


				    // DA commentare geneazione output comando
				    // Get the input stream and read from it
				    InputStream in = child.getInputStream();
				    int c;
				    while ((c = in.read()) != -1) {
				        System.out.print((char)c);
				    }
				    in.close();

			} catch (IOException e) {
					e.printStackTrace();
				}
				 */

			}else {
				
				// nessun messaggio in coda mi fermo fino al prossimo
				block();
			}

		}	

		private void eventToMconsole(Event event){
			Provisioner pro = new Provisioner();
			if ( pro.executeJob(event)){
				log.info("Aggiornata vista con successo");
				pro.restart();
			}
			else 
				log.info("Errore in fase di aggiornamento viste");
		}
	}
}
